home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / PEAR / Validate.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  22.0 KB  |  624 lines

  1. <?php
  2. /**
  3.  * PEAR_Validate
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Greg Beaver <cellog@php.net>
  16.  * @copyright  1997-2005 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: Validate.php,v 1.44 2005/11/14 14:07:43 cellog Exp $
  19.  * @link       http://pear.php.net/package/PEAR
  20.  * @since      File available since Release 1.4.0a1
  21.  */
  22. /**#@+
  23.  * Constants for install stage
  24.  */
  25. define('PEAR_VALIDATE_INSTALLING', 1);
  26. define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
  27. define('PEAR_VALIDATE_NORMAL', 3);
  28. define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
  29. define('PEAR_VALIDATE_PACKAGING', 7);
  30. /**#@-*/
  31. require_once 'PEAR/Common.php';
  32. require_once 'PEAR/Validator/PECL.php';
  33.  
  34. /**
  35.  * Validation class for package.xml - channel-level advanced validation
  36.  * @category   pear
  37.  * @package    PEAR
  38.  * @author     Greg Beaver <cellog@php.net>
  39.  * @copyright  1997-2005 The PHP Group
  40.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  41.  * @version    Release: 1.4.5
  42.  * @link       http://pear.php.net/package/PEAR
  43.  * @since      Class available since Release 1.4.0a1
  44.  */
  45. class PEAR_Validate
  46. {
  47.     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
  48.     /**
  49.      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
  50.      */
  51.     var $_packagexml;
  52.     /**
  53.      * @var int one of the PEAR_VALIDATE_* constants
  54.      */
  55.     var $_state = PEAR_VALIDATE_NORMAL;
  56.     /**
  57.      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
  58.      * @var array
  59.      * @access private
  60.      */
  61.     var $_failures = array('error' => array(), 'warning' => array());
  62.  
  63.     /**
  64.      * Override this method to handle validation of normal package names
  65.      * @param string
  66.      * @return bool
  67.      * @access protected
  68.      */
  69.     function _validPackageName($name)
  70.     {
  71.         return (bool) preg_match('/^' . $this->packageregex . '$/', $name);
  72.     }
  73.  
  74.     /**
  75.      * @param string package name to validate
  76.      * @param string name of channel-specific validation package
  77.      * @final
  78.      */
  79.     function validPackageName($name, $validatepackagename = false)
  80.     {
  81.         if ($validatepackagename) {
  82.             if (strtolower($name) == strtolower($validatepackagename)) {
  83.                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*$/', $name);
  84.             }
  85.         }
  86.         return $this->_validPackageName($name);
  87.     }
  88.  
  89.     /**
  90.      * This validates a bundle name, and bundle names must conform
  91.      * to the PEAR naming convention, so the method is final and static.
  92.      * @param string
  93.      * @final
  94.      * @static
  95.      */
  96.     function validGroupName($name)
  97.     {
  98.         return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/', $name);
  99.     }
  100.  
  101.     /**
  102.      * Determine whether $state represents a valid stability level
  103.      * @param string
  104.      * @return bool
  105.      * @static
  106.      * @final
  107.      */
  108.     function validState($state)
  109.     {
  110.         return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
  111.     }
  112.  
  113.     /**
  114.      * Get a list of valid stability levels
  115.      * @return array
  116.      * @static
  117.      * @final
  118.      */
  119.     function getValidStates()
  120.     {
  121.         return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
  122.     }
  123.  
  124.     /**
  125.      * Determine whether a version is a properly formatted version number that can be used
  126.      * by version_compare
  127.      * @param string
  128.      * @return bool
  129.      * @static
  130.      * @final
  131.      */
  132.     function validVersion($ver)
  133.     {
  134.         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
  135.     }
  136.  
  137.     /**
  138.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  139.      */
  140.     function setPackageFile(&$pf)
  141.     {
  142.         $this->_packagexml = &$pf;
  143.     }
  144.  
  145.     /**
  146.      * @access private
  147.      */
  148.     function _addFailure($field, $reason)
  149.     {
  150.         $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
  151.     }
  152.  
  153.     /**
  154.      * @access private
  155.      */
  156.     function _addWarning($field, $reason)
  157.     {
  158.         $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
  159.     }
  160.  
  161.     function getFailures()
  162.     {
  163.         $failures = $this->_failures;
  164.         $this->_failures = array('warnings' => array(), 'errors' => array());
  165.         return $failures;
  166.     }
  167.  
  168.     /**
  169.      * @param int one of the PEAR_VALIDATE_* constants
  170.      */
  171.     function validate($state = null)
  172.     {
  173.         if (!isset($this->_packagexml)) {
  174.             return false;
  175.         }
  176.         if ($state !== null) {
  177.             $this->_state = $state;
  178.         }
  179.         $this->_failures = array('warnings' => array(), 'errors' => array());
  180.         $this->validatePackageName();
  181.         $this->validateVersion();
  182.         $this->validateMaintainers();
  183.         $this->validateDate();
  184.         $this->validateSummary();
  185.         $this->validateDescription();
  186.         $this->validateLicense();
  187.         $this->validateNotes();
  188.         if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
  189.             $this->validateState();
  190.             $this->validateFilelist();
  191.         } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0') {
  192.             $this->validateTime();
  193.             $this->validateStability();
  194.             $this->validateDeps();
  195.             $this->validateMainFilelist();
  196.             $this->validateReleaseFilelist();
  197.             //$this->validateGlobalTasks();
  198.             $this->validateChangelog();
  199.         }
  200.         return !((bool) count($this->_failures['errors']));
  201.     }
  202.  
  203.     /**
  204.      * @access protected
  205.      */
  206.     function validatePackageName()
  207.     {
  208.         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
  209.               $this->_state == PEAR_VALIDATE_NORMAL) {
  210.             if ($this->_packagexml->getPackagexmlVersion() == '2.0' &&
  211.                   $this->_packagexml->getExtends()) {
  212.                 $version = $this->_packagexml->getVersion() . '';
  213.                 $name = $this->_packagexml->getPackage();
  214.                 $test = array_shift($a = explode('.', $version));
  215.                 if ($test == '0') {
  216.                     return true;
  217.                 }
  218.                 $vlen = strlen($test);
  219.                 $majver = substr($name, strlen($name) - $vlen);
  220.                 while ($majver && !is_numeric($majver{0})) {
  221.                     $majver = substr($majver, 1);
  222.                 }
  223.                 if ($majver != $test) {
  224.                     $this->_addWarning('package', "package $name extends package " .
  225.                         $this->_packagexml->getExtends() . ' and so the name should ' .
  226.                         'have a postfix equal to the major version like "' .
  227.                         $this->_packagexml->getExtends() . $test . '"');
  228.                     return true;
  229.                 } elseif (substr($name, 0, strlen($name) - $vlen) !=
  230.                             $this->_packagexml->getExtends()) {
  231.                     $this->_addWarning('package', "package $name extends package " .
  232.                         $this->_packagexml->getExtends() . ' and so the name must ' .
  233.                         'be an extension like "' . $this->_packagexml->getExtends() .
  234.                         $test . '"');
  235.                     return true;
  236.                 }
  237.             }
  238.         }
  239.         if (!$this->validPackageName($this->_packagexml->getPackage())) {
  240.             $this->_addFailure('name', 'package name "' .
  241.                 $this->_packagexml->getPackage() . '" is invalid');
  242.             return false;
  243.         }
  244.     }
  245.  
  246.     /**
  247.      * @access protected
  248.      */
  249.     function validateVersion()
  250.     {
  251.         if ($this->_state != PEAR_VALIDATE_PACKAGING) {
  252.             if (!$this->validVersion($this->_packagexml->getVersion())) {
  253.                 $this->_addFailure('version',
  254.                     'Invalid version number "' . $this->_packagexml->getVersion() . '"');
  255.             }
  256.             return false;
  257.         }
  258.         $version = $this->_packagexml->getVersion();
  259.         $versioncomponents = explode('.', $version);
  260.         if (count($versioncomponents) != 3) {
  261.             $this->_addWarning('version',
  262.                 'A version number should have 3 decimals (x.y.z)');
  263.             return true;
  264.         }
  265.         $name = $this->_packagexml->getPackage();
  266.         // version must be based upon state
  267.         switch ($this->_packagexml->getState()) {
  268.             case 'snapshot' :
  269.                 return true;
  270.             case 'devel' :
  271.                 if ($versioncomponents[0] . 'a' == '0a') {
  272.                     return true;
  273.                 }
  274.                 if ($versioncomponents[0] == 0) {
  275.                     $versioncomponents[0] = '0';
  276.                     $this->_addWarning('version',
  277.                         'version "' . $version . '" should be "' .
  278.                         implode('.' ,$versioncomponents) . '"');
  279.                 } else {
  280.                     $this->_addWarning('version',
  281.                         'packages with devel stability must be < version 1.0.0');
  282.                 }
  283.                 return true;
  284.             break;
  285.             case 'alpha' :
  286.             case 'beta' :
  287.                 // check for a package that extends a package,
  288.                 // like Foo and Foo2
  289.                 if (!$this->_packagexml->getExtends()) {
  290.                     if ($versioncomponents[0] == '1') {
  291.                         if ($versioncomponents[2]{0} == '0') {
  292.                             if ($versioncomponents[2] == '0') {
  293.                                 // version 1.*.0000
  294.                                 $this->_addWarning('version',
  295.                                     'version 1.' . $versioncomponents[1] .
  296.                                         '.0 probably should not be alpha or beta');
  297.                                 return true;
  298.                             } elseif (strlen($versioncomponents[2]) > 1) {
  299.                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
  300.                                 return true;
  301.                             } else {
  302.                                 // version 1.*.0
  303.                                 $this->_addWarning('version',
  304.                                     'version 1.' . $versioncomponents[1] .
  305.                                         '.0 probably should not be alpha or beta');
  306.                                 return true;
  307.                             }
  308.                         } else {
  309.                             $this->_addWarning('version',
  310.                                 'bugfix versions (1.3.x where x > 0) probably should ' .
  311.                                 'not be alpha or beta');
  312.                             return true;
  313.                         }
  314.                     } elseif ($versioncomponents[0] != '0') {
  315.                         $this->_addWarning('version',
  316.                             'major versions greater than 1 are not allowed for packages ' .
  317.                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
  318.                         return true;
  319.                     }
  320.                     if ($versioncomponents[0] . 'a' == '0a') {
  321.                         return true;
  322.                     }
  323.                     if ($versioncomponents[0] == 0) {
  324.                         $versioncomponents[0] = '0';
  325.                         $this->_addWarning('version',
  326.                             'version "' . $version . '" should be "' .
  327.                             implode('.' ,$versioncomponents) . '"');
  328.                     }
  329.                 } else {
  330.                     $vlen = strlen($versioncomponents[0] . '');
  331.                     $majver = substr($name, strlen($name) - $vlen);
  332.                     while ($majver && !is_numeric($majver{0})) {
  333.                         $majver = substr($majver, 1);
  334.                     }
  335.                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
  336.                         $this->_addWarning('version', 'first version number "' .
  337.                             $versioncomponents[0] . '" must match the postfix of ' .
  338.                             'package name "' . $name . '" (' .
  339.                             $majver . ')');
  340.                         return true;
  341.                     }
  342.                     if ($versioncomponents[0] == $majver) {
  343.                         if ($versioncomponents[2]{0} == '0') {
  344.                             if ($versioncomponents[2] == '0') {
  345.                                 // version 2.*.0000
  346.                                 $this->_addWarning('version',
  347.                                     "version $majver." . $versioncomponents[1] .
  348.                                         '.0 probably should not be alpha or beta');
  349.                                 return false;
  350.                             } elseif (strlen($versioncomponents[2]) > 1) {
  351.                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
  352.                                 return true;
  353.                             } else {
  354.                                 // version 2.*.0
  355.                                 $this->_addWarning('version',
  356.                                     "version $majver." . $versioncomponents[1] .
  357.                                         '.0 cannot be alpha or beta');
  358.                                 return true;
  359.                             }
  360.                         } else {
  361.                             $this->_addWarning('version',
  362.                                 "bugfix versions ($majver.x.y where y > 0) should " .
  363.                                 'not be alpha or beta');
  364.                             return true;
  365.                         }
  366.                     } elseif ($versioncomponents[0] != '0') {
  367.                         $this->_addWarning('version',
  368.                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
  369.                         return true;
  370.                     }
  371.                     if ($versioncomponents[0] . 'a' == '0a') {
  372.                         return true;
  373.                     }
  374.                     if ($versioncomponents[0] == 0) {
  375.                         $versioncomponents[0] = '0';
  376.                         $this->_addWarning('version',
  377.                             'version "' . $version . '" should be "' .
  378.                             implode('.' ,$versioncomponents) . '"');
  379.                     }
  380.                 }
  381.                 return true;
  382.             break;
  383.             case 'stable' :
  384.                 if ($versioncomponents[0] == '0') {
  385.                     $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
  386.                     'be stable');
  387.                     return true;
  388.                 }
  389.                 if (!is_numeric($versioncomponents[2])) {
  390.                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
  391.                           $versioncomponents[2])) {
  392.                         $this->_addWarning('version', 'version "' . $version . '" or any ' .
  393.                             'RC/beta/alpha version cannot be stable');
  394.                         return true;
  395.                     }
  396.                 }
  397.                 // check for a package that extends a package,
  398.                 // like Foo and Foo2
  399.                 if ($this->_packagexml->getExtends()) {
  400.                     $vlen = strlen($versioncomponents[0] . '');
  401.                     $majver = substr($name, strlen($name) - $vlen);
  402.                     while ($majver && !is_numeric($majver{0})) {
  403.                         $majver = substr($majver, 1);
  404.                     }
  405.                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
  406.                         $this->_addWarning('version', 'first version number "' .
  407.                             $versioncomponents[0] . '" must match the postfix of ' .
  408.                             'package name "' . $name . '" (' .
  409.                             $majver . ')');
  410.                         return true;
  411.                     }
  412.                 } elseif ($versioncomponents[0] > 1) {
  413.                     $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
  414.                         '1 for any package that does not have an <extends> tag');
  415.                 }
  416.                 return true;
  417.             break;
  418.             default :
  419.                 return false;
  420.             break;
  421.         }
  422.     }
  423.  
  424.     /**
  425.      * @access protected
  426.      */
  427.     function validateMaintainers()
  428.     {
  429.         // maintainers can only be truly validated server-side for most channels
  430.         // but allow this customization for those who wish it
  431.         return true;
  432.     }
  433.  
  434.     /**
  435.      * @access protected
  436.      */
  437.     function validateDate()
  438.     {
  439.         if ($this->_state == PEAR_VALIDATE_NORMAL ||
  440.               $this->_state == PEAR_VALIDATE_PACKAGING) {
  441.             if (!preg_match('/\d\d\d\d\-\d\d\-\d\d/',
  442.                   $this->_packagexml->getDate())) {
  443.                 $this->_addFailure('date', 'invalid release date "' .
  444.                     $this->_packagexml->getDate() . '"');
  445.                 return false;
  446.             }
  447.             if (strtotime($this->_packagexml->getDate()) == -1) {
  448.                 $this->_addFailure('date', 'invalid release date "' .
  449.                     $this->_packagexml->getDate() . '"');
  450.                 return false;
  451.             }
  452.             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
  453.                   $this->_packagexml->getDate() != date('Y-m-d')) {
  454.                 $this->_addWarning('date', 'Release Date "' .
  455.                     $this->_packagexml->getDate() . '" is not today');
  456.             }
  457.         }
  458.         return true;
  459.     }
  460.  
  461.     /**
  462.      * @access protected
  463.      */
  464.     function validateTime()
  465.     {
  466.         if (!$this->_packagexml->getTime()) {
  467.             // default of no time value set
  468.             return true;
  469.         }
  470.         // packager automatically sets time, so only validate if
  471.         // pear validate is called
  472.         if ($this->_state = PEAR_VALIDATE_NORMAL) {
  473.             if (!preg_match('/\d\d:\d\d:\d\d/',
  474.                   $this->_packagexml->getTime())) {
  475.                 $this->_addFailure('time', 'invalid release time "' .
  476.                     $this->_packagexml->getTime() . '"');
  477.                 return false;
  478.             }
  479.             if (strtotime($this->_packagexml->getTime()) == -1) {
  480.                 $this->_addFailure('time', 'invalid release time "' .
  481.                     $this->_packagexml->getTime() . '"');
  482.                 return false;
  483.             }
  484.         }
  485.         return true;
  486.     }
  487.  
  488.     /**
  489.      * @access protected
  490.      */
  491.     function validateState()
  492.     {
  493.         // this is the closest to "final" php4 can get
  494.         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
  495.             if (strtolower($this->_packagexml->getState() == 'rc')) {
  496.                 $this->_addFailure('state', 'RC is not a state, it is a version ' .
  497.                     'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
  498.             }
  499.             $this->_addFailure('state', 'invalid release state "' .
  500.                 $this->_packagexml->getState() . '", must be one of: ' .
  501.                 implode(', ', PEAR_Validate::getValidStates()));
  502.             return false;
  503.         }
  504.         return true;
  505.     }
  506.  
  507.     /**
  508.      * @access protected
  509.      */
  510.     function validateStability()
  511.     {
  512.         $ret = true;
  513.         $packagestability = $this->_packagexml->getState();
  514.         $apistability = $this->_packagexml->getState('api');
  515.         if (!PEAR_Validate::validState($packagestability)) {
  516.             $this->_addFailure('state', 'invalid release stability "' .
  517.                 $this->_packagexml->getState() . '", must be one of: ' .
  518.                 implode(', ', PEAR_Validate::getValidStates()));
  519.             $ret = false;
  520.         }
  521.         $apistates = PEAR_Validate::getValidStates();
  522.         array_shift($apistates); // snapshot is not allowed
  523.         if (!in_array($apistability, $apistates)) {
  524.             $this->_addFailure('state', 'invalid API stability "' .
  525.                 $this->_packagexml->getState('api') . '", must be one of: ' .
  526.                 implode(', ', $apistates));
  527.             $ret = false;
  528.         }
  529.         return $ret;
  530.     }
  531.  
  532.     /**
  533.      * @access protected
  534.      */
  535.     function validateSummary()
  536.     {
  537.         return true;
  538.     }
  539.  
  540.     /**
  541.      * @access protected
  542.      */
  543.     function validateDescription()
  544.     {
  545.         return true;
  546.     }
  547.  
  548.     /**
  549.      * @access protected
  550.      */
  551.     function validateLicense()
  552.     {
  553.         return true;
  554.     }
  555.  
  556.     /**
  557.      * @access protected
  558.      */
  559.     function validateNotes()
  560.     {
  561.         return true;
  562.     }
  563.  
  564.     /**
  565.      * for package.xml 2.0 only - channels can't use package.xml 1.0
  566.      * @access protected
  567.      */
  568.     function validateDependencies()
  569.     {
  570.         return true;
  571.     }
  572.  
  573.     /**
  574.      * for package.xml 1.0 only
  575.      * @access private
  576.      */
  577.     function _validateFilelist()
  578.     {
  579.         return true; // placeholder for now
  580.     }
  581.  
  582.     /**
  583.      * for package.xml 2.0 only
  584.      * @access protected
  585.      */
  586.     function validateMainFilelist()
  587.     {
  588.         return true; // placeholder for now
  589.     }
  590.  
  591.     /**
  592.      * for package.xml 2.0 only
  593.      * @access protected
  594.      */
  595.     function validateReleaseFilelist()
  596.     {
  597.         return true; // placeholder for now
  598.     }
  599.  
  600.     /**
  601.      * @access protected
  602.      */
  603.     function validateChangelog()
  604.     {
  605.         return true;
  606.     }
  607.  
  608.     /**
  609.      * @access protected
  610.      */
  611.     function validateFilelist()
  612.     {
  613.         return true;
  614.     }
  615.  
  616.     /**
  617.      * @access protected
  618.      */
  619.     function validateDeps()
  620.     {
  621.         return true;
  622.     }
  623. }
  624. ?>